#ifndef CONNECTIONPOLL_H
#define CONNECTIONPOLL_H

#include "Connection.h"

#include <mutex> // 队列queue的操作一定是线程安全的，所以用到互斥锁
#include <queue>
#include <string>
#include <atomic>
#include <thread>  // for 启动一个新的线程作为连接的producer
#include <memory>
#include <functional>
#include <condition_variable>    // 线程间通信 

using namespace std;

/* 实现连接池功能模块 */

class ConnectionPool
{
public:
    // 获取连接池对象实例
    static ConnectionPool *getConnectionPool();

    // 给外部提供一个API， 从连接池中获取一个可用的空闲连接
    // 用智能指针管理，以及重定义删除资源的方式：来归还可用的连接到连接池
    std::shared_ptr<Connection> getIdleConn();

    // 数据库连接池配置初始化
    bool init();

private:
    ConnectionPool(const ConnectionPool &) = delete;
    ConnectionPool &operator=(const ConnectionPool &) = delete;

    // 单例模式：构造函数私有化
    ConnectionPool();
    // 从mysql.cnf配置文件中加载配置项
    bool loadConfigFile();

    // 生产连接线程函数
    void produceConnectionTask();

    // 扫描超过_maxIdleTime秒的空闲连接， 进行多余的连接回收
    void scanningConnectionTask();

    std::string _ip;       // mysql地址
    unsigned short _port;  // mysql端口号
    std::string _username; // mysql登录用户名
    std::string _password; // mysql登录密码
    std::string _dbname;   // 数据库名称 
    int _initSize;         // 池启动时创建的连接数量
    int _maxSize;          // 最大连接数
    int _maxIdleTime;      // 连接超时时间
    int _maxLatencyTime;   // 最大等待时间

    std::mutex _queueMutex;                  // 维护连接队列的线程安全互斥锁
    std::queue<Connection *> _connectionQue; // 存储mysql连接的队列
    std::atomic<int> _connCnt;    // 记录已创建的connection连接的总数据 <= _maxSize
    std::condition_variable _cv;  // 设置条件变量用于produce线程和consumer线程的同步通信
};

#endif